/***************************************************************************
 *   mgpi_g2dmdl.c - 2D Graphics Definitions                               *
 *   Copyright (C) 2008 by cmaster.matso                                   *
 *   cmaster.matso@gmail.com                                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "mgpi_g2dmdl.h"

/**
 * Loads from file an image of the given name.
 */
SDL_Surface *g2dLoadImage(const char *name) {
	SDL_Surface *ptr = (SDL_Surface *) IMG_Load(name);
	if (!ptr) MGPI_PostMessagef("%s: %s", __FUN__, IMG_GetError());
    return ptr;
}

/**
 * Loads an image of the given name and draw it on the given surface.
 */
MGPI_BOOL g2dDrawImage(SDL_Surface *surface, const char *name, int x, int y) {
    SDL_Surface *tmp = g2dLoadImage(name);
    SDL_Rect src, dest;

    if (!tmp || !surface) {
    	MGPI_PostMessagef("%s: %s", __FUN__, IMG_GetError());
    	return MGPI_FALSE;
    }

    tmp = SDL_DisplayFormat(tmp);

    src.x = 0;
    src.y = 0;
    src.w = tmp->w;
    src.h = tmp->h;

    dest.x = x;
    dest.y = y;
    dest.w = tmp->w;
    dest.h = tmp->h;

    SDL_BlitSurface(tmp, &src, surface, &dest);
    SDL_FreeSurface(tmp);

    return MGPI_TRUE;
}

/**
 * Draws the given source surface to the given destination surface.
 */
MGPI_BOOL g2dDrawSurface(SDL_Surface *dest_surf, SDL_Surface *src_surf, int x, int y) {
    SDL_Surface *tmp;
    SDL_Rect src, dest;

    if (!dest_surf || !src_surf) return MGPI_FALSE;

    tmp = SDL_DisplayFormat(src_surf);

    src.x = 0;
    src.y = 0;
    src.w = tmp->w;
    src.h = tmp->h;

    dest.x = x;
    dest.y = y;
    dest.w = tmp->w;
    dest.h = tmp->h;

    SDL_BlitSurface(tmp, &src, dest_surf, &dest);
    SDL_FreeSurface(tmp);

    return MGPI_TRUE;
}

/**
 * Splits the given image into an array of sub images of given width and height.
 */
MGPI_BOOL g2dSplitImage(graphic_t *g[], int glen, SDL_Surface *image, int w, int h) {/* TEST IT!!! */
    int i = 0, x, y;
    x = y = 0;

    if (!g || !image || !w || !h || !glen) return MGPI_FALSE;

    while (i < glen && (y + h) < image->h) {
        g[i]->image = g2dClipImage(image, x, y, w, h);
        if ((x + w) == image->w) {
            x = -w;
            y += h;
        }
        x += w;
        ++i;
    }

    return MGPI_TRUE;
}

/**
 * Clips the given image by the sizes and position given.
 */
SDL_Surface *g2dClipImage(SDL_Surface *image, int x, int y, int w, int h) {/* TEST IT!!! */
    void *pixels = malloc(w * h * image->format->BitsPerPixel);
    SDL_Surface *simg = (SDL_Surface *) SDL_CreateRGBSurfaceFrom(pixels, w, h, image->format->BitsPerPixel,
            image->pitch,
            image->format->Rmask, image->format->Gmask,
            image->format->Bmask,
            image->format->Amask);
    SDL_Rect src, dest;

    src.x = x;
    src.y = y;
    src.w = w;
    src.h = h;

    dest.x = 0;
    dest.y = 0;
    dest.w = w;
    dest.h = h;

    SDL_BlitSurface(image, &src, simg, &dest);

    return (simg) ? simg : NULL;
}

/**
 * Gets pixel unsigned integer value form the given surface position.
 */
Uint32 g2dGetPixel(SDL_Surface *surface, int x, int y) {
    int bpp = surface->format->BytesPerPixel;

    Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * bpp;

    switch (bpp) {
        case 1:
            return *p;

        case 2:
            return *(Uint16 *) p;

        case 3:
            if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
                return p[0] << 16 | p[1] << 8 | p[2];
            else
                return p[0] | p[1] << 8 | p[2] << 16;

        case 4:
            return *(Uint32 *) p;

        default:
            return 0;
    }
}

/**
 * Sets a given pixel unsigned integer value to the position given upon the surface.
 */
void g2dPutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel) {
    int bpp = surface->format->BytesPerPixel;
    Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * bpp;

    switch (bpp) {
        case 1:
            *p = pixel;
            break;

        case 2:
            *(Uint16 *) p = pixel;
            break;

        case 3:
            if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
                p[0] = (pixel >> 16) & 0xff;
                p[1] = (pixel >> 8) & 0xff;
                p[2] = pixel & 0xff;
            } else {
                p[0] = pixel & 0xff;
                p[1] = (pixel >> 8) & 0xff;
                p[2] = (pixel >> 16) & 0xff;
            }
            break;

        case 4:
            *(Uint32 *) p = pixel;
            break;
    }
}
